package com.codeduck.mp.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.LocalCacheScope;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.io.FileNotFoundException;

/**
 * @author: codeduck@163.com
 * @since: 2021-05-31
 */
@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = "com.codeduck.druid.mapper", sqlSessionFactoryRef = "sqlSessionFactory")
@DependsOn("metaObjectHandler")
public class DataSourceConfig {

    private final static Logger LOGGER = LoggerFactory.getLogger(DataSourceConfig.class);

    static final String MAPPER_LOCATION = "classpath:mybatis/*.xml";

    @Resource
    private SnowflakeIdConfig snowflakeIdConfig;

    @Resource
    private MybatisPlusMetaObjectHandler metaObjectHandler;

    @Bean(name = "dataSourceMaster")
    @ConfigurationProperties("spring.datasource.mysql")
    public DataSource dataSourceMaster() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = "transactionManager")
    public DataSourceTransactionManager transactionManager(@Qualifier("dataSourceMaster") DataSource dataSource) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(dataSourceMaster());
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }

    @Bean
    @Qualifier("sqlSessionFactory")
    public MybatisSqlSessionFactoryBean sqlSessionFactory(@Qualifier("dataSourceMaster") DataSource dataSource) throws FileNotFoundException {
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        sqlSessionFactory.setTypeAliasesPackage("com.codeduck.druid.entity");
//        sqlSessionFactory.setMapperLocations(
//                new PathMatchingResourcePatternResolver().getResource(DataSourceConfig.MAPPER_LOCATION));

        GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();
        // 逻辑删除配置
        dbConfig.setLogicDeleteField("status");
        dbConfig.setLogicDeleteValue("0");
        dbConfig.setLogicNotDeleteValue("1");

        GlobalConfig globalConfig = new GlobalConfig();
        // 设置自动填充字段配置信息
        globalConfig.setMetaObjectHandler(metaObjectHandler);
        globalConfig.setDbConfig(dbConfig);

        // Id生成器
        globalConfig.setIdentifierGenerator(snowflakeIdConfig);
        sqlSessionFactory.setGlobalConfig(globalConfig);

        // 关闭一级缓存:存在数据一致性问题
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setLocalCacheScope(LocalCacheScope.STATEMENT);
        sqlSessionFactory.setConfiguration(configuration);
        // 设置最大分页
        sqlSessionFactory.setPlugins(mybatisPlusInterceptor());

        LOGGER.info("mybatis plus config finished $_$");
        return sqlSessionFactory;
    }

    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        PaginationInnerInterceptor interceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        interceptor.setOverflow(false);
        interceptor.setMaxLimit(1000L);
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(interceptor);
        return mybatisPlusInterceptor;
    }

}
